package proTrack;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Query;

import proTrack.model.Account;
import proTrack.model.Job;
import proTrack.model.State;

/**
 *	Some useful methods.
 *
 */
public class Operation {

    private EntityManagerFactory factory;

    private Account currentAccount;

	private String accountName;

	private EntityManager manager;

    public Operation(final EntityManagerFactory factory) {
        this.factory = factory;
    }


	private void createManager() {
    	if (manager == null) {
    		manager = factory.createEntityManager();
            manager.getTransaction().begin();		
    	}
    }
    
    public void commit() {
    	if (manager == null) {
    		return;
    	}
    	manager.getTransaction().commit();
    	manager.close();
    	manager = null;
    }
    
    public void rollback() {
    	if (manager == null) {
    		return;
    	}
    	manager.getTransaction().rollback();
    	manager.close();
    	manager = null;
    }
    
    public void exit() {
		commit();
		
	}
    
    public void createUser(final String name, final String password) {
        
        Account existing = manager.find(Account.class, name);
        if (existing != null) {
            throw new RuntimeException("User already exists");
        } else {
            manager.persist(new Account(name, password));
        }

    }

    public List<Account> getAllAccounts() {
        createManager();

        Query query = manager.createNamedQuery("AllAccounts");
        List<Account> list = query.getResultList();

        return list;
    }
    
    public List<? extends Object> getAllStates() {
    	createManager();
    	
        Query query = manager.createNamedQuery("AllStates");
        List<State> list = query.getResultList();

        return list;
	}

    public void createJob(final String description, final String handler, final String stateName) {
    	createManager();
    	
    	State state = getState(stateName);
        Account account = getAccount(handler);
        Job j = new Job(description, account, getCurrentUser(), state);
        manager.persist(j);

    }
    
    public void createState(final String name) {
    	createManager();
    	
        State state = new State(name);
        manager.persist(state);

    }


	private Account getAccount(final String name) {
		createManager();
		return manager.find(Account.class, name);
	}
	
	private State getState(final String stateName) {
		Query query = manager.createNamedQuery("StateByName"); 
		query.setParameter(1, stateName);
		State s = (State) query.getSingleResult();
		return s;
	}

	public List<Job> getJobs(final String name, final String parameter, final Class<?> parameterType) {
		createManager();

        Query query = manager.createNamedQuery(name);
        if (parameter != null) {
        	Object param;
        	if (parameterType.equals(Account.class)) {
        		param = getAccount(parameter);
        	} else {
        		param = (parameter);
        	}
        	query.setParameter(1, param);
        }
        List<Job> list = query.getResultList();

        return list;
    }

    public void setJobNextState(final String jobId, final String nextState) {
    	createManager();

        int identifier = Integer.parseInt(jobId);
        Job job = manager.find(Job.class, identifier);
        job.setState(getState(nextState));
        manager.merge(job);
    }

	public void deleteUser(final String name) {
		createManager();

        Query q = manager.createNamedQuery("deleteAccount");
        q.setParameter(1, name);
        q.executeUpdate();

	}

	public void deleteJob(final String identifier) {
		createManager();

        Query q = manager.createNamedQuery("DeleteJob");
        q.setParameter(1, Integer.parseInt(identifier));
        q.executeUpdate();
	}

	public void deleteState(final String name) {
		createManager();
		Query q = manager.createNamedQuery("DeleteState");
        q.setParameter(1, name);
        q.executeUpdate();
		
	}

	
	
	private Account getCurrentUser() {
		 if (currentAccount == null) {
			 currentAccount = getAccount(accountName);

		 }
		 return currentAccount;
	 }

	public void setSuccessor(final String state1, final String state2) {
		createManager();

        State s1 = getState(state1);
        State s2 = getState(state2);
        s1.addSuccessor(s2, -1);
        
        manager.merge(s1);
	}


	public void setAccount(final Account acc) {
		// TODO store Account instead of the name!
		this.accountName = acc.getName();
		
	}

	

}
